from jili.trade.adapter.ctp.adapter_ctp import adapter_ctp
import threading
import queue
from jili.trade.adapter.ctp import dictmap as dm
def str2bytes(s):
    if isinstance(s, str):
        s = bytes(s, encoding="gbk")
    elif isinstance(s, dict):
        for k, v in s.items():
            if isinstance(v, str):
                s[k] = bytes(v, encoding="gbk")
    return s
"""
主要是粘合 adpaterapi<-->adapter_xx的core层，实现标准的处理
frame标准：
0.核心版本获取与维护getversion()  @staticmethod
1.一个账户创建一个核心实例 create(investorid, config) @staticmethod  #实例
2.login(req)入口
adapterapi标准：

"""
class ctp_core(adapter_ctp):
    coretype="ctp"
    @staticmethod
    def create(investorid, config):
        gpath = config["tmppath"]
        path = gpath + investorid
        path = str2bytes(path)
        print(investorid, "path:", path)
        trader=adapter_ctp.CreateFtdcTraderApi(path)
        trader.initvar(config)
        trader.init(config)
        return trader

    @staticmethod
    def getversion():
        version = str(adapter_ctp.CThostFtdcTraderApi.GetApiVersion(), encoding="gbk")
        return "core version:"+ adapter_ctp.version+"CTP version: " + version
    def initvar(self,config):
        self.__timer = threading.Timer(1, self.__dealqryQueue)
        self.__timer.start()
        self.__qryQueue = queue.Queue()
        self.__undoubleqryQueue = []
        self.requstid="ctp_core"
        self.orders={}
    def qry_safe(self, req):
        rsq=req["data"]
        if self.__qryQueue.empty():
            self.__qryQueue.put(rsq)
            self.__undoubleqryQueue.append(rsq["cmd"])
            if not self.__timer.is_alive():
                self.__dealqryQueue()
        else:
            if rsq["cmd"] not in self.__undoubleqryQueue:
                self.__qryQueue.put(rsq)
                self.__undoubleqryQueue.append(rsq["cmd"])
                #ontype="OnRsq"+rsq["cmd"]
                ontype = "OnRsq" + req["cmd"][3:]
                self.idmapunicall[ontype]=[rsq["RequestID"]]
            else:
                ontype = "OnRsq" + req["cmd"][3:]
                self.idmapunicall[ontype].append(rsq["RequestID"])
    def __dealqryQueue(self):
        if not self.__qryQueue.empty():
            req = self.__qryQueue.get()
            self.__undoubleqryQueue.remove(req["cmd"])
            cmd=req["cmd"]
            if hasattr(self, cmd):
                getattr(self, cmd)(req)
            else:
                self.senderror(req["RequestID"], self.investorid, "no this cmd,please check you code or cmd first")

            self.__timer = threading.Timer(1, self.__dealqryQueue)
            self.__timer.start()
    def login(self,req):
        rst=[]
        if self.isconnect:
            if self.isauth:
                rsq = {"UserID": req["investorid"], "Password": req["password"]}
                req.update(rsq)
                ret=self.Login(req)
                if  ret[0]== 0:
                    rst[0] = 0
                    rst[1] = ""
                    if ret[1]==1:
                        self.confirmsettlementInfo()
                        self.qryorder()
                        self.qrytrade()
                        self.qryfund()
                        self.qrypos()
                else:
                    rst[0] = 3
                    rst[1] = "login fail:"+str(ret[1])
            else:
                rst[0] = 2
                rst[1] = "auth fail"
        else:
            if self.Connect() == 0:
                brokerid=req["brokerid"]
                investorid=req["investorid"]
                if self.reqAuthenticate(brokerid, investorid) == 0:
                    rsq={"UserID":req["investorid"],"Password":req["password"]}
                    req.update(rsq)
                    ret = self.Login(req)
                    if ret[0] == 0:
                        rst[0] = 0
                        rst[1] = ""
                        if ret[1] == 1:
                            self.confirmsettlementInfo()
                            self.qryfund()
                            self.qryorder()
                            self.qrypos()
                    else:
                        rst[0] = 3
                        rst[1] = "login fail:" + str(ret[1])
                else:
                    rst[0] = 2
                    rst[1] = "auth fail"
            else:
                rst[0] = 2
                rst[1] = "connect fail"
    def logout(self,req):
        self.Logout(req)
    def submitorder(self,req):
        self.orders[req["orderid"]]=req
        ctp_req = {
            "InstrumentID": req.obj,
            "ExchangeID": req.market,
            "LimitPrice": req.price,
            "VolumeTotalOriginal": int(req.qty),
            "OrderPriceType": self.THOST_FTDC_OPT_LimitPrice,
            "Direction": dm.bs_ats2ctp.get(req.bs, ""),
            "CombOffsetFlag": dm.openclose_ats2ctp.get(req.openclsoe, ""),
            "orderid": self.orderid,
            "CombHedgeFlag": self.THOST_FTDC_HF_Speculation,
            "ContingentCondition": self.THOST_FTDC_CC_Immediately,
            "ForceCloseReason": self.THOST_FTDC_FCC_NotForceClose,
            "IsAutoSuspend": 0,
            "TimeCondition": self.THOST_FTDC_TC_GFD,
            "VolumeCondition": self.THOST_FTDC_VC_AV,
            "MinVolume": 1
        }
        self.reqOrderInsert(ctp_req)
    def cancelorder(self,req):
        sys_orderid=req["sys_orderid"]
        sys_orderid=sys_orderid.split(".")
        orderid=req["orderid"]
        ctp_req = dict(
            cmd='reqOrderAction'
            , OrderRef=sys_orderid[2]
            , FrontID=sys_orderid[0]
            , SessionID=sys_orderid[1]
            , InstrumentID=req["obj"]
            , ExchangeID=dm.market_ctp2ats(req["marketcode"])
            , ActionFlag='0'
            , RequestID=orderid
            , orderid=orderid
        )
        self.reqOrderAction(ctp_req)
    def qrytrade(self,req):
        req = dict(cmd='reqQryTrade')
        self.timerqry(req)
    def confirmsettlementInfo(self):
        if not self.issettlementInfoconfirm:
            ReqSettlementInfoConfirm=dict(
                cmd='reqSettlementInfoConfirm'
                ,ConfirmDate=''
                ,ConfirmTime=''
                , RequestID = self.requstid
            )
            self.timerqry(ReqSettlementInfoConfirm)
    def qrypos(self):
        req = dict(cmd='reqQryInvestorPosition',RequestID=self.requstid)
        self.timerqry(req)
    def qryfund(self):
        req=dict( cmd='reqQryTradingAccount',BizType="1",RequestID=self.requstid)
        self.timerqry(req)
    def qryorder(self):
        req=dict( cmd='reqQryOrder',RequestID=self.requstid)
        self.timerqry(req)
    def qrytrade(self):
        req=dict( cmd='reqQryTrade',RequestID=self.requstid)
        self.timerqry(req)
    def qrysettlement(self):
        req=dict( cmd='reqQrySettlementInfo',RequestID=self.requstid)
        self.timerqry(req)
    def onpos(self,pos):
        pass
    def onorder(self,order,ordertype):
        pass
    def onfund(self,fund):
        pass
    def ontrade(self,trade):
        pass
    def onerror(self,err):
        pass